#include <accent/algorithms/rotate.hpp>
#include <accent/algorithms/concat.hpp>
#include "test_base.hpp"

template <typename Traversal>
class ConcatRotate : public ::testing::Test {};

typedef ::testing::Types<forward_traversal_tag, bidirectional_traversal_tag,
                         random_access_traversal_tag>
  traversals;
TYPED_TEST_CASE(ConcatRotate, traversals);

template <typename Traversal, typename... Containers>
auto concatc(Containers&... containers)
  -> decltype(limit_traversal<Traversal>(concat(all(containers)...)))
{
  return limit_traversal<Traversal>(concat(all(containers)...));
}

TYPED_TEST(ConcatRotate, rotateZero)
{
  ivec v1 = { 1, 2 }, v2 = { 3, 4 },
       e1 = { 1, 2 }, e2 = { 3, 4 };
  auto r = concatc<TypeParam>(v1, v2), s = r;
  auto p = rotate(r, s.front_position());
  ASSERT_EQ(e1, v1);
  ASSERT_EQ(e2, v2);
  ASSERT_FALSE(!p);
  ASSERT_EQ(1, *p);
}

TYPED_TEST(ConcatRotate, rotateOne)
{
  ivec v1 = { 1, 2 }, v2 = { 3, 4 },
       e1 = { 2, 3 }, e2 = { 4, 1 };
  auto r = concatc<TypeParam>(v1, v2), s = r;
  s.pop_front();
  auto p = rotate(r, s.front_position());
  ASSERT_EQ(e1, v1);
  ASSERT_EQ(e2, v2);
  ASSERT_FALSE(!p);
  ASSERT_EQ(1, *p);
}

TYPED_TEST(ConcatRotate, rotateTwo)
{
  ivec v1 = { 1, 2 }, v2 = { 3, 4 },
       e1 = { 3, 4 }, e2 = { 1, 2 };
  auto r = concatc<TypeParam>(v1, v2), s = r;
  s.pop_front();
  s.pop_front();
  auto p = rotate(r, s.front_position());
  ASSERT_EQ(e1, v1);
  ASSERT_EQ(e2, v2);
  ASSERT_FALSE(!p);
  ASSERT_EQ(1, *p);
}

TYPED_TEST(ConcatRotate, rotateThree)
{
  ivec v1 = { 1, 2 }, v2 = { 3, 4 },
       e1 = { 4, 1 }, e2 = { 2, 3 };
  auto r = concatc<TypeParam>(v1, v2), s = r;
  s.pop_front();
  s.pop_front();
  s.pop_front();
  auto p = rotate(r, s.front_position());
  ASSERT_EQ(e1, v1);
  ASSERT_EQ(e2, v2);
  ASSERT_FALSE(!p);
  ASSERT_EQ(1, *p);
}
